import binascii
import gm_key_manager
import gm_sm4_encrypt_decrypt
import gm_sm2_apply


# 使用工作密钥加密本地公文内容
def encrypt_local_document(content):
    """
    使用SM4工作密钥和随机初始向量加密本地公文内容。

    :param content: 本地公文内容，类型应为字符串等可加密的数据格式。
    :return: 返回加密的内容与IV值组成的元组，如果加密出现异常则返回 (None, None)。
    """
    try:
        iv = gm_key_manager.get_random_sm4_key_or_iv_bytes()
        result_encrypt = gm_sm4_encrypt_decrypt.sm4_encrypt_text(gm_key_manager.get_work_key_hex(), content, iv)
        return result_encrypt, iv
    except Exception as e:
        # 记录详细的错误日志，方便后续排查问题，这里只是简单打印，可以集成日志模块进行更规范记录
        print(f"加密内容时出现异常: {e}")
        return None, None


# 使用工作密钥解密本地公文内容
def decrypt_local_document(encrypted_content, iv):
    """
    使用工作密钥和初始向量解密本地公文内容。

    :param encrypted_content: 经过加密的公文内容。
    :param iv: 加密时使用的初始向量。
    :return: 返回解密后的内容，如果解密出现异常则返回 None。
    """
    try:
        result_decrypt = gm_sm4_encrypt_decrypt.sm4_decrypt_text(gm_key_manager.get_work_key_hex(), encrypted_content, iv)
        return result_decrypt
    except Exception as e:
        print(f"解密内容时出现异常: {e}")
        return None


# 将字节数据转换为十六进制字符串表示
def byte_to_hex(new_bytes):
    """
    将字节类型的数据转换为十六进制字符串格式。

    :param new_bytes: 输入的字节类型数据。
    :return: 对应的十六进制字符串。
    """
    return binascii.hexlify(new_bytes).decode('utf-8')


# 对输入字典进行加密并添加签名操作，实现数字信封相关流程
def encrypt_and_sign_document(input_dict, receiving_unit):
    """
    对输入的字典数据执行加密及签名操作，实现数字信封相关流程，保障数据传输的保密性、完整性和可验证性。

    步骤如下：
    1. 根据接收单位获取对应的加密公钥。
    2. 按照要求随机生成合适长度的SM4密钥和初始向量（IV）。
    3. 使用SM4算法加密整个字典内容。
    4. 使用接收单位的公钥对生成的SM4密钥进行加密，构建数字信封。
    5. 计算字典数据的SM3哈希值，并使用自己的私钥对哈希值进行签名。

    :param input_dict: 需要加密和签名的字典数据，包含了要传输的业务相关信息等。
    :param receiving_unit: 接收数据的单位标识，用于获取对应接收单位的相关密钥。
    :return: 返回包含加密后的字典、加密后的SM4密钥、初始向量（IV）以及签名结果的元组，顺序依次对应。
    """
    # 1. 根据接受单位获取加密公钥
    receiving_unit_encrypt_public_key = gm_key_manager.get_receiving_unit_encrypt_public_key(receiving_unit)

    # 2. 随机生成SM4密钥和IV值（示例简单用固定长度随机字节表示，实际按对应要求生成）
    sm4_key = gm_key_manager.get_random_sm4_key_or_iv_bytes()  # 假设SM4密钥长度为16字节，实际需严格按标准生成

    iv = gm_key_manager.get_random_sm4_key_or_iv_bytes()  # 假设IV长度为16字节，实际应遵循相关规范
    # 可添加对生成的sm4_key和iv的长度等合法性校验逻辑，此处暂省略

    # 3. 使用SM4算法加密整个字典
    encrypted_dict = gm_sm4_encrypt_decrypt.sm4_encrypt_dict(sm4_key, input_dict, iv)

    # 4. 使用对方公钥加密SM4密钥
    encrypted_sm4_key = gm_sm2_apply.encrypt_sm4_key_with_public_key(sm4_key, receiving_unit_encrypt_public_key)

    # 5. 计算字典的SM3哈希值，使用自己的私钥签名字典的SM3哈希值
    signature_hex = gm_sm2_apply.sm3_hash_and_sign_dict(input_dict, gm_key_manager.get_sign_private_key_hex(), gm_key_manager.get_verify_public_key_hex())

    return encrypted_dict, encrypted_sm4_key, iv, signature_hex


# 对加密的字典进行解密并验证签名操作
def decrypt_and_verify_document(encrypted_dict, receiving_unit, encrypted_sm4_key, iv, signature):
    """
    对接收的加密字典执行解密及签名验证操作，以获取原始数据并确认数据的完整性和来源合法性。

    步骤如下：
    1. 获取自己的解密私钥和对应接收单位的验证公钥。
    2. 使用私钥解密SM4密钥。
    3. 使用解密后的SM4密钥和对应的初始向量（IV）对加密的字典进行解密。
    4. 使用接收单位的验证公钥验证签名的有效性。

    :param encrypted_dict: 接收到的已经加密的字典数据。
    :param receiving_unit: 数据的接收单位标识，用于获取对应密钥进行验证等操作。
    :param encrypted_sm4_key: 经过接收单位公钥加密后的SM4密钥。
    :param iv: 加密字典时使用的初始向量。
    :param signature: 发送方对字典数据生成的签名信息。
    :return: 返回包含解密后的字典以及签名验证结果（布尔值，True表示验证通过，False表示验证失败）的元组。
    """
    # 1. 获取自己的解密私钥和对方的验证公钥
    decrypt_private_key_hex = gm_key_manager.get_decrypt_private_key()
    receiving_unit_verify_public_key_hex = gm_key_manager.get_receiving_unit_verify_public_key(receiving_unit)

    # 2. 使用私钥解密SM4密钥
    decrypted_sm4_key = gm_sm2_apply.decrypt_sm4_key_with_private_key(encrypted_sm4_key, decrypt_private_key_hex)

    # 3. 使用SM4密钥和对应的初始向量（IV）对加密的字典进行解密
    decrypted_dict = gm_sm4_encrypt_decrypt.sm4_decrypt_dict(decrypted_sm4_key, encrypted_dict, iv)

    # 4. 使用公钥验证签名
    verification_result = gm_sm2_apply.verify_dict_signature(decrypted_dict, signature, receiving_unit_verify_public_key_hex)

    return decrypted_dict, verification_result


if __name__ == "__main__":
    # # 模拟本地公文内容（这里简单使用一个字符串示例，实际可以是从文件读取等获取的内容）
    # local_document_content = "这是一份重要的本地公文内容示例"
    # # 加密本地公文内容
    # encrypted_result, iv_value = encrypt_local_document(local_document_content)
    # if encrypted_result and iv_value:
    #     print("加密后的数据:", encrypted_result)
    #     print("IV值:", iv_value)
    #     # 解密加密后的公文内容
    #     decrypted_result = decrypt_local_document(encrypted_result, iv_value)
    #     if decrypted_result:
    #         print("解密后还原的内容:", decrypted_result)
    #
    # # 测试公共公文所需的数字信封流程
    # test_dit = {'receiving_unit': "123456"}
    # encrypted_dict, encrypted_sm4_key, iv, signature = encrypt_and_sign_document(test_dit, test_dit["receiving_unit"])
    # print("encrypted_dict, encrypted_sm4_key, iv, signature: ", encrypted_dict, encrypted_sm4_key, iv, signature)
    # print("signature: ", signature)
    # decrypted_dict, verification_result = decrypt_and_verify_document(encrypted_dict, "receiving_unit",
    #                                                         encrypted_sm4_key, iv, signature)
    # print("decrypted_dict, verification_result: ", decrypted_dict, verification_result)
    pass
